/*
 * Copyright (c) 2016 4PX Information Technology Co.,Ltd. All rights reserved.
 */
package com.open.spring.utils.soap.proxy;

import java.net.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.client.core.SoapFaultMessageResolver;
import org.springframework.ws.support.DefaultStrategiesHelper;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.HttpUrlConnectionMessageSender;

/**
 * WebServiceTemplate 设置翻墙代理
 * 
 * @author hcx
 * @date 2017年7月24日
 */
public class WebServiceTemplateEx extends WebServiceTemplate {

    private Proxy proxy;

    private Map<String, String> headerMap;

    /**
     * Creates a new {@code MarshallingMethodEndpointAdapter} with the given marshaller and unmarshaller.
     * 
     * @param marshaller the marshaller to use
     * @param unmarshaller the unmarshaller to use
     * @param proxy null is allowed
     * @param headerMap null is allowed
     * @since 2.0.3
     */
    public WebServiceTemplateEx(Marshaller marshaller, Unmarshaller unmarshaller, Proxy proxy,
            Map<String, String> headerMap) {
        super();
        Assert.notNull(marshaller, "marshaller must not be null");
        Assert.notNull(unmarshaller, "unmarshaller must not be null");
        this.setMarshaller(marshaller);
        this.setUnmarshaller(unmarshaller);
        this.setProxy(proxy);
        this.setHeaderMap(headerMap);
        initDefaultStrategiesEx();
    }

    /**
     * Creates a new {@code MarshallingMethodEndpointAdapter} with the given marshaller and unmarshaller.
     * 
     * @param marshaller the marshaller to use
     * @param unmarshaller the unmarshaller to use
     * @since 2.0.3
     */
    public WebServiceTemplateEx(Marshaller marshaller, Unmarshaller unmarshaller, Proxy proxy) {
        super();
        Assert.notNull(marshaller, "marshaller must not be null");
        Assert.notNull(unmarshaller, "unmarshaller must not be null");
        this.setMarshaller(marshaller);
        this.setUnmarshaller(unmarshaller);
        this.setProxy(proxy);
        initDefaultStrategiesEx();

    }

    /**
     * Creates a new {@code WebServiceTemplate} based on the given message factory.
     * 
     * @param messageFactory the message factory to use
     */
    public WebServiceTemplateEx(WebServiceMessageFactory messageFactory, Proxy proxy) {
        super(messageFactory);
        this.proxy = proxy;
    }

    /**
     * Initialize the default implementations for the template's strategies: {@link SoapFaultMessageResolver},
     * {@link org.springframework.ws.soap.saaj.SaajSoapMessageFactory}, and {@link HttpUrlConnectionMessageSender}.
     * 
     * @throws BeanInitializationException in case of initalization errors
     * @see #setFaultMessageResolver(FaultMessageResolver)
     * @see #setMessageFactory(WebServiceMessageFactory)
     * @see #setMessageSender(WebServiceMessageSender)
     */
    @Override
    protected void initDefaultStrategies() {

    }

    protected void initDefaultStrategiesEx() {
        DefaultStrategiesHelper strategiesHelper = new DefaultStrategiesHelper(WebServiceTemplate.class);
        if (getMessageFactory() == null) {
            initMessageFactory(strategiesHelper);
        }
        if (ObjectUtils.isEmpty(getMessageSenders())) {
            initMessageSenders(this.proxy, this.headerMap);
        }
        if (getFaultMessageResolver() == null) {
            initFaultMessageResolver(strategiesHelper);
        }
    }

    private void initMessageFactory(DefaultStrategiesHelper helper) throws BeanInitializationException {
        WebServiceMessageFactory messageFactory = helper.getDefaultStrategy(WebServiceMessageFactory.class);
        setMessageFactory(messageFactory);
    }

    private void initMessageSenders(Proxy proxy, Map<String, String> headerMap) {
        List<WebServiceMessageSender> messageSenders = new ArrayList<WebServiceMessageSender>();
        HttpUrlConnectionMessageSenderEx messageSender = new HttpUrlConnectionMessageSenderEx();
        messageSender.setProxy(proxy);
        messageSender.setHeaderMap(headerMap);
        messageSenders.add(messageSender);
        setMessageSenders(messageSenders.toArray(new WebServiceMessageSender[messageSenders.size()]));
    }

    private void initFaultMessageResolver(DefaultStrategiesHelper helper) throws BeanInitializationException {
        FaultMessageResolver faultMessageResolver = helper.getDefaultStrategy(FaultMessageResolver.class);
        setFaultMessageResolver(faultMessageResolver);
    }

    /**
     * @return the proxy
     */
    public Proxy getProxy() {
        return proxy;
    }

    /**
     * @param proxy the proxy to set
     */
    public void setProxy(Proxy proxy) {
        this.proxy = proxy;
    }

    /**
     * @return the headerMap
     */
    public Map<String, String> getHeaderMap() {
        return headerMap;
    }

    /**
     * @param headerMap the headerMap to set
     */
    public void setHeaderMap(Map<String, String> headerMap) {
        this.headerMap = headerMap;
    }

}
